`include "./parameters.v"

module addr_ctr (
	input					clk,
	input					rst_n,
	input					start,
	input		[5:0]		model,

	input		[3:0]		open_addr0,
	input		[3:0]		open_addr1,
	input		[3:0]		result_addr,

	input					read_req,

	input					valid_o,
	input					valid_o_rej,
	input					valid_o_bin,

	output	reg [`A_W-1:0]	addr0,
	output	reg [`A_W-1:0]	addr1,
	output	reg [`A_W-1:0]	addr2,	
	output	reg [`A_W-1:0]	addr3,

	output	reg [2:0]		width_type,
	output	reg [2:0]		read_width_type,
	output	reg				flag	
	);
//*****************************************
//	width_type:
//				3'd1:	32
// 				3'd2:	40
// 				3'd3:	64
// 				3'd4:	80
// 				3'd5:	96
//				3'd6:	88

	// reg flag;//0表示addr0数据有效，1表示addr1数据有效
	reg [7:0] read_cnt;//记录读数周期
	// reg		  read_req_buffer;
	// reg 	  read_en;
	reg  	  flag_buffer;
	reg  	  flag_buffer1;

	reg		  seed0,seed1,seed2;

	always@(*)
	begin
		case(model)
			`PK2:	seed0 = 1'b0;
			`PK3:	seed0 = 1'b0;
			`PK4:	seed0 = 1'b0;
			`CT2:	seed0 = 1'b0;
			`CT3:	seed0 = 1'b0;
			`CT4:	seed0 = 1'b0;
			default:seed0 = 1'b1;
		endcase // model	
	end		

	always@(*)
	begin
		case(model)
			`CT2:	seed1 = 1'b0;
			`CT3:	seed1 = 1'b0;
			`CT4:	seed1 = 1'b0;
			default:seed1 = 1'b1;
		endcase // model	
	end	

	always@(*)
	begin
		case(model[5:4])
			`SHAKE128:	seed2 = 1'b0;
			`SHAKE256:	seed2 = model[3:0] != 4'b1110 ? 1'b0 : 1'b1;
			default:	seed2 = 1'b1;
		endcase // model	
	end


	always@(posedge clk or negedge rst_n)//记录读数周期
	begin
		if(!rst_n)
			read_cnt <= 8'b0;
		else if(start)
			read_cnt <= 8'b0;
		else if(read_req)
			read_cnt <= read_cnt + 1'b1;
		else
			read_cnt <= read_cnt;
	end

	always@(posedge clk or negedge rst_n)//0表示addr0数据有效，1表示addr1数据有效
	begin
		if(!rst_n)
			flag_buffer <= 1'b0;
		else if(start)
			flag_buffer <= 1'b0;
		else
		begin
			case(model)
				`PK2:	flag_buffer <= read_cnt < 8'd63  ? 1'b0 : 1'b1;
				`PK3:	flag_buffer <= read_cnt < 8'd95  ? 1'b0 : 1'b1;
				`PK4:	flag_buffer <= read_cnt < 8'd127 ? 1'b0 : 1'b1;
				`CT2:	flag_buffer <= read_cnt < 8'd63  ? 1'b0 : 1'b1;
				`CT3:	flag_buffer <= read_cnt < 8'd96	 ? 1'b0 : 1'b1;
				`CT4:	flag_buffer <= read_cnt < 8'd127 ? 1'b0 : 1'b1;
				`KDF:	flag_buffer <= read_cnt < 8'd2   ? 1'b0 : 1'b1;
				`M_PK:	flag_buffer <= read_cnt < 8'd2 	 ? 1'b0 : 1'b1;
				default	flag_buffer <= 1'b0;
			endcase // model
		end
	end

	always@(posedge clk or negedge rst_n)//地址切换延迟两拍
	begin
		if(!rst_n)
			flag <= 1'b0;
		else
			flag <= flag_buffer;
	end

	always@(posedge clk or negedge rst_n)//地址切换延迟两拍
	begin
		if(!rst_n)
			flag_buffer1 <= 1'b0;
		else
			flag_buffer1 <= flag;
	end

	always@(*)
	begin
		case(model)
			`PK2,`PK3,`PK4:	width_type = flag_buffer ? 3'd3 : 3'd5;
			`CT2,`CT3:		width_type = flag_buffer ? 3'd1 : 3'd4;
			`CT4:			width_type = flag_buffer ? 3'd2 : 3'd6;	
			default:		width_type = 3'd3;
		endcase // model
	end

	always@(*)
	begin
		case(model)
			`PK2,`PK3,`PK4:	read_width_type = flag_buffer1 ? 3'd3 : 3'd5;
			`CT2,`CT3:		read_width_type = flag_buffer1 ? 3'd1 : 3'd4;
			`CT4:			read_width_type = flag_buffer1 ? 3'd2 : 3'd6;	
			default:		read_width_type = 3'd3;
		endcase // model
	end			
//***********************************地址管理**********************************************
	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			addr0 <= `A_W'b0;
		else if(start)
		begin
			if(seed0)
				addr0 <= {3'b100,open_addr0,2'b0};
			else
				addr0 <= {open_addr0,5'b0};
		end
		else if(~flag && read_req)
			addr0 <= addr0 + 1'b1;
		else
			addr0 <= addr0;
	end

	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			addr1 <= `A_W'b0;
		else if(start)
		begin
			if(seed1)
				addr1 <= {3'b100,open_addr1,2'b0};
			else
				addr1 <= {open_addr1,5'b0};
		end
		else if(flag && read_req)
			addr1 <= addr1 + 1'b1;
		else
			addr1 <= addr1;
	end

	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
		begin
			addr2 <= `A_W'b0;	addr3 <= `A_W'b0;
		end
		else if(start)
		begin
			if(seed2)
			begin
				addr2 <= {3'b100,result_addr,2'b0};	addr3 <= {3'b100,result_addr,2'b1};
			end
			else
			begin
				addr2 <= {result_addr,5'b0};	addr3 <= {result_addr,5'b1};
			end
		end
		else
		begin
			case({valid_o,valid_o_rej,valid_o_bin})
				3'b110:	begin	addr2 <= addr2 + 9'd1;	addr3 <= addr3;	end
				3'b101:	begin	addr2 <= addr2 + 9'd2;	addr3 <= addr3 + 9'd2;	end
				3'b100: begin	addr2 <= addr2 + 9'd2;	addr3 <= addr3 + 9'd2;	end
				default:begin	addr2 <= addr2;			addr3 <= addr3;	end
			endcase // {valid_o,valid_o_rej,valid_o_bin}
		end
	end
//*********************************************************************************




endmodule